<script setup lang="ts">
import { Delete, Edit, Plus } from '@element-plus/icons-vue'
import { onMounted, reactive, ref, nextTick } from 'vue'
import { ElMessageBox, ElTree, FormInstance, FormRules } from 'element-plus'
import type { Role, RoleMenuResponse, RoleMenuVo } from '@/api/role/type'
import {
  addRoleRequest,
  assignMenuToRoleRequest,
  deleteRoleRequest,
  queryAllRolesRequest,
  queryRolePossessedMenusRequest,
  updateRoleRequest,
} from '@/api/role'
import { queryAllMenusRequest } from '@/api/menu'
import type { MenuVo } from '@/api/menu/type'
import { useUserStore } from '@/stores/userStore'

// 对话框展示控制符：true-弹出；false-隐藏
const dialogTableVisible = ref(false)
// 添加角色按钮单击事件
const showDialogTable = () => {
  role.value.name = ''
  dialogTableVisible.value = true
  nextTick(() => {
    ruleFormRef.value.clearValidate('name')
  })
}
// 角色
const role = ref<Role>({ id: 0, name: '', normalizedName: '', concurrencyStamp: 0 })
const ruleFormRef = ref<FormInstance>()
// 添加角色表单校验规则
const rules = reactive<FormRules>({
  name: [
    { required: true, message: '请输入角色名称', trigger: 'blur' },
    { min: 2, max: 50, message: '角色名称在2到50之间', trigger: 'change' },
  ],
})
// 保存角色信息单击事件
const addRole = () => {
  ruleFormRef.value.validate(async (valid) => {
    if (valid) {
      if (role.value.id === 0) {
        await addRoleRequest(role.value.name)
          .then((res) => {
            if (res.succeeded) {
              dialogTableVisible.value = false
            } else if (res.errors[0].code === 'DuplicateRoleName') {
              console.log(res.errors[0])
              ElMessageBox.alert('该角色已存在，请重新输入')
            }
          })
          .then(() => queryAllROles())
          .catch((err) => console.log(err))
      } else {
        await updateRoleRequest(role.value)
          .then((res) => {
            if (res.succeeded) {
              dialogTableVisible.value = false
            } else if (res.errors[0].code === 'DuplicateRoleName') {
              console.log(res.errors[0])
              ElMessageBox.alert('该角色已存在，请重新输入')
            }
          })
          .then(() => queryAllROles(currentPage.value, pageSize.value))
          .catch((err) => console.log(err))
      }
    }
  })
}
// 当前页码
const currentPage = ref(1)
// 每页长度
const pageSize = ref(4)
// 总条数
const total = ref(0)
// 角色信息集合
const roleVos = ref<Role[]>()
// 改变每页长度事件
const handleSizeChange = async (val: number) => {
  pageSize.value = val
  await queryAllROles(
    currentPage.value,
    pageSize.value,
    roleName.value === '' ? '%20' : roleName.value,
  )
}
// 改变页码之后重新查询
const handleCurrentChange = async (val: number) => {
  currentPage.value = val
  await queryAllROles(
    currentPage.value,
    pageSize.value,
    roleName.value === '' ? '%20' : roleName.value,
  )
}
// 根据条件查询角色信息
const queryAllROles = async (pageIndex = 1, pageSize = 4, condition = '%20') => {
  await queryAllRolesRequest(pageIndex, pageSize, condition).then((res) => {
    roleVos.value = res.items
    total.value = res.count
  })
}
// 进入页面之后先查询全部角色信息
onMounted(async () => {
  await queryAllROles()
})
// 角色名称-搜索框绑定对象
const roleName = ref<string>('')
// 搜索按钮单击事件
const searchRoles = async () => {
  await queryAllROles(
    currentPage.value,
    pageSize.value,
    roleName.value === '' ? '%20' : roleName.value,
  )
}
// 重置表单
const resetForm = () => {
  roleName.value = ''
}
// 选中当前行
const editRole = (data: Role) => {
  Object.assign(role.value, data)
  dialogTableVisible.value = true
}
// 控制抽屉打开关闭,true-打开；false-关闭
const drawerVisible = ref(false)
// 菜单集合
const menuVos = ref<MenuVo[]>([])
// 用户已有的权限在打开权限树时默认选中
let menuIds = ref<number[]>([])
// 分配角色按钮单击事件
const assignPermission = async (row: Role) => {
  roleMenuVo.value = { roleId: 0, menuIdList: [] }
  drawerVisible.value = true
  roleMenuVo.value.roleId = row.id
  // 查询全部权限
  await queryAllMenusRequest()
    .then((res) => {
      menuVos.value = res
      // 查询角色已有的权限
      return queryRolePossessedMenusRequest(roleMenuVo.value.roleId)
    })
    .then((res) => {
      menuIds.value = []
      res.forEach((menuId) => {
        menuIds.value.push(menuId)
      })
    })
}
const defaultProps = {
  children: 'children',
  label: 'menuName',
}
// 树实例
const tree = ref()
// 角色权限对象
let roleMenuVo = ref<RoleMenuVo>({ roleId: 0, menuIdList: [] })
// 分配权限抽屉确定按钮单击事件
const savePermission = async () => {
  tree.value.getCheckedNodes(false, false).forEach((node: MenuVo) => {
    roleMenuVo.value.menuIdList.push(node.menuID)
  })
  // 发送请求，保存角色权限
  await assignMenuToRoleRequest(roleMenuVo.value).then(() => queryAllROles())
  drawerVisible.value = false
}
// 确定删除角色按钮单击事件
const deleteRole = async (row: Role) => {
  await deleteRoleRequest(row).then(() => queryAllROles())
}
// 引入用户仓库
const userStore = useUserStore()
const buttons = userStore.buttons
</script>

<template>
  <div class="container">
    <!--    搜索角色卡片-->
    <el-card class="search-card">
      <el-form class="search-form" :model="roleName">
        <el-form-item label="角色名称" style="width: 20rem">
          <el-input placeholder="请输入角色名称" v-model="roleName"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="searchRoles">搜索</el-button>
          <el-button @click="resetForm">重置</el-button>
        </el-form-item>
      </el-form>
    </el-card>
    <!--    展示角色卡片-->
    <el-card class="list-card">
      <!--      添加角色按钮-->
      <el-button
        type="primary"
        :icon="Plus"
        @click="showDialogTable"
        v-if="buttons?.includes('AddRole')"
      >
        添加角色
      </el-button>
      <el-scrollbar class="el-scrollbar">
        <!--      角色列表-->
        <el-table border :data="roleVos">
          <el-table-column type="selection" align="center" width="180" />
          <el-table-column type="index" prop="id" label="序号" align="center" width="180" />
          <el-table-column prop="name" label="角色名称" align="center" width="180" />
          <el-table-column label="操作" align="center" width="400">
            <template #default="scope">
              <el-button
                type="primary"
                @click="assignPermission(scope.row)"
                v-if="buttons?.includes('AssignPermission')"
              >
                分配权限
              </el-button>
              <el-button
                :icon="Edit"
                type="primary"
                @click="editRole(scope.row)"
                v-if="buttons?.includes('EditRole')"
              >
                编辑
              </el-button>
              <el-popconfirm title="确定要删除吗?" @confirm="deleteRole(scope.row)">
                <template #reference>
                  <el-button :icon="Delete" type="danger" v-if="buttons?.includes('DeleteRole')">
                    删除
                  </el-button>
                </template>
              </el-popconfirm>
            </template>
          </el-table-column>
        </el-table>
      </el-scrollbar>
      <el-pagination
        background
        layout="total, sizes, prev, pager, next, jumper"
        :total="total"
        v-model:current-page="currentPage"
        v-model:page-size="pageSize"
        :page-sizes="[4, 10, 50]"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
    </el-card>
    <!--      添加角色对话框-->
    <el-dialog :title="role.id === 0 ? '添加角色' : '修改角色'" v-model="dialogTableVisible">
      <el-form ref="ruleFormRef" :model="role" :rules="rules">
        <el-form-item label="角色名称" prop="name">
          <el-input placeholder="请输入角色名称" v-model="role.name"></el-input>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="dialogTableVisible = false">取消</el-button>
          <el-button type="primary" @click="addRole">确定</el-button>
        </div>
      </template>
    </el-dialog>
    <el-drawer v-model="drawerVisible" direction="rtl" title="分配权限">
      <div class="assign-permission">
        <el-tree
          ref="tree"
          :data="menuVos"
          show-checkbox
          :props="defaultProps"
          :default-expanded-keys="menuIds"
          :default-checked-keys="menuIds"
          node-key="menuID"
        ></el-tree>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="drawerVisible = false">取消</el-button>
          <el-button type="primary" @click="savePermission">确定</el-button>
        </div>
      </template>
    </el-drawer>
  </div>
</template>

<style scoped>
.container {
  padding: 1rem;

  .search-card {
    margin-bottom: 1rem;

    .search-form {
      display: flex;
      align-items: center;
      justify-content: space-between;
    }
  }

  .list-card {
    .el-scrollbar {
      padding: 1rem 0;
    }
  }
}
</style>
